package ups.Schedule;

import ups.Schedule.ScheduleItem;
import org.htmlparser.Tag;
import org.htmlparser.Text;
import org.htmlparser.visitors.NodeVisitor;

import java.util.Stack;
import java.util.Hashtable;
import java.util.ArrayList;

public class ScheduleVisitor extends NodeVisitor {
	
	private Stack<Tag> 			tagStack;
	private Hashtable<Integer,String> shipIDToNameMap; 
	
	private DaysOfWeek 			currentOperationDay;
	private String 				currentPort;
	private ScheduleTime		currentTime;
	private int					currentVesselID;
	
	private ArrayList<ScheduleItem> scheduleItems;
	
	private int	internalOrder = 0;
	
	public ScheduleVisitor() {
		tagStack = new Stack<Tag>();
		shipIDToNameMap = new Hashtable<Integer,String>();
		scheduleItems = new ArrayList<ScheduleItem>();
	}
	
	public ArrayList<ScheduleItem> scheduleItems() {
		return scheduleItems;
	}
	
	static int X = 0;
	static int Y = 0;
	public void visitTag (Tag tag) {
		String tagName = tag.getTagName();
		
		if( tagName.equals(			"BODY" )) {
			push( tag );
		} else if( tagName.equals(	"HTML")) {
			push( tag );
		} else if(	tagName.equals( "SPAN" 	)) {
			push( tag );
		} else if(	tagName.equals( "STRONG")) {
			push( tag );
		} else if(	tagName.equals( "TABLE"	)) {
			X = 1;
			Y = 1;
			push( tag );
		} else if( 	tagName.equals( "TR"	)) {
			Y++;
			X = 1;
			push( tag );
		} else if(	tagName.equals(	"TD"	)) {
			X++;
			push( tag );
		} else if( tagName.equals(	"A" 	)) {
			push( tag );
		} else if (tagName.equals(	"IMG"	)) {
			// We don't care about img tags
		} else if( tagName.equals(	"TITLE"	)) {
			// We don't care about TITLE
		} else {
		//	System.out.println( tagName );
		}
	}

	public void push( Tag t ) {
		tagStack.push( t );
	}
		
	public void visitEndTag( Tag tag ) {
		while( true && ! tagStack.empty()) {
			Tag t = tagStack.pop();
			if( t.getTagName().equals( tag.getTagName() )) {
				break;
			}
		}
	}
	
    public void visitStringNode (Text string) {
    	if( tagStack.size() >= 2 ) {
    		Tag t0 = tagStack.get( tagStack.size() - 1);
    		Tag t1 = tagStack.get( tagStack.size() - 2);
    		
			/* Looking for Days of Operation */
			if( t0.getTagName().equals("STRONG") &&
				t1.getTagName().equals("SPAN")	 &&
				t1.getAttribute("CLASS") != null &&
				t1.getAttribute("CLASS").equals("sched_DayOP")) {
					if( string.getText().equals("Daily")) {
						currentOperationDay =  DaysOfWeek.Daily;
					} else if( string.getText().equals("Saturday and Sunday")) {
						currentOperationDay =  DaysOfWeek.Saturday_And_Sunday;	
					} else if( string.getText().equals("Monday through Friday")) {
						currentOperationDay = DaysOfWeek.Monday_Through_Friday;
					} else if( string.getText().equals("Monday thru Friday (Except Holidays)")) {
						currentOperationDay = DaysOfWeek.Monday_Thru_Friday_Except_Holidays;
					} else if( string.getText().equals("Saturday, Sunday and Holidays")) {
						currentOperationDay = DaysOfWeek.Saturday_Sunday_and_Holidays;
					} else if( string.getText().equals("Monday through Friday and Holidays")) {
						currentOperationDay = DaysOfWeek.Monday_Through_Friday_and_Holidays;
					} else {
						System.out.println("got an operation day we can't handle: *" + string.getText() + "*");
					}
			}
			
			/* Looking For A Leaving From */
    		if( t0.getTagName().equals("A") 					&&
    			t1.getTagName().equals("SPAN")	 				&&
				t1.getAttribute("CLASS") != null 				&&
				t1.getAttribute("CLASS").equals("content_text") &&
				t0.getAttribute("HREF").indexOf("/ferries/info_desk/terminals/") != -1 ) {
					currentPort = string.getText().substring( "Leave ".length() );
    		}

			/* Looking for a Time */
    		if( t0.getTagName().equals( "SPAN") 	&&
   				t1.getTagName().equals( "TD") 		&&
   				t1.getAttribute("CLASS") != null 	&&
   				t1.getAttribute("CLASS").equals("sched_time") ) {
    			if( string.getText().equals("Noon")) {
    				currentTime = new ScheduleTime( "12:00", t0.getAttribute("CLASS").equals("sched_timeam"));
    			} else if (string.getText().equals("Midnight")) {
    				currentTime = new ScheduleTime( "12:00", t0.getAttribute("CLASS").equals("sched_timeam"));
    			} else {
    				currentTime = new ScheduleTime( string.getText(), t0.getAttribute("CLASS").equals("sched_timeam"));
    			}
    		}
    		
			/* Looking For A Vessel ID */
    		if( t0.getTagName().equals("A") 		&&
    			t1.getTagName().equals("TD") 		&&
    			t0.getAttribute("CLASS") != null 	&&
    			t0.getAttribute("CLASS").equals( "sched_vesselPosition")) {
					currentVesselID = new Integer( string.getText() ).intValue();
					ScheduleItem item = new ScheduleItem( currentTime, shipIDToNameMap.get( new Integer( currentVesselID )), currentPort, currentOperationDay );
					item.setInternalOrder( X * 4 + Y );
					internalOrder++;
					scheduleItems.add(item);
    		}
    		
    		
    		/* Looking For A Vessel ID In the Ship Names List*/
    		/* This is based off a TYPO (vesselPosition vs. vesselposition) */
    		if( t0.getTagName().equals("A") 		&&
    			t1.getTagName().equals("TD") 		&&
    			t0.getAttribute("CLASS") != null 	&&
    			t0.getAttribute("CLASS").equals( "sched_vesselposition")) {
					currentVesselID = new Integer( string.getText() ).intValue();
    		}

			/* Looking for Ship Names to ID Map */
    		if( t0.getTagName().equals("A") 					&&
    			t1.getTagName().equals("TD") 					&&
				t0.getAttribute("CLASS") != null 				&&
				t0.getAttribute("CLASS").equals("sched_text1") 	&&
				t1.getAttribute("CLASS") != null				&&
				t1.getAttribute("CLASS").equals("sched_text1")	&&
			 	string.getText().startsWith("M/V"))  {
					shipIDToNameMap.put( new Integer( currentVesselID), string.getText().substring( "M/V".length() ));
				}
       	}
	}
}
